home *** CD-ROM | disk | FTP | other *** search
- Path: news.delphi.com!jodle
- From: jodle@bix.com (jodle)
- Newsgroups: comp.lang.c++
- Subject: Re: polymorphism and style
- Date: 3 Mar 1996 02:10:51 GMT
- Organization: BIX
- Message-ID: <4hav3b$m26@news2.delphi.com>
- References: <4gr4ur$n13@alpha.pcix.com> <DnI6II.KMt@news.arco.com> <4h4h3h$6ur@brtph500.bnr.ca> <4has16$cge@werple.net.au>
- NNTP-Posting-Host: bix.com
- X-Newsreader: TIN [version 1.2 PL2]
-
- David White (davidw@werple.net.au) wrote:
-
- : There are many occasions when this is not practical. Suppose I have an
- : array of base class object pointers; at some stage I might want to iterate
- : over them, retrieve the derived classes, and call functions specific to the
- : derived type. Or I might pass an object pointer to something and receive
- : it back later and have to retrieve the derived class. These are exactly
- : the kinds of situations that 'dynamic_cast' was intended for. Your
- : suggestion can unnecessarily complicate the design, rather than simplify
- : it. To state, without qualification, that "this is clearly a design fault"
- : demonstrates ignorance of real situations in OO design. And this from an
- : OO helpline!
-
- I agree that the form of the message was inappropriate; an absolute
- condemnation of the design is not in order. However, my experience is
- that this kind of situation generally arises from a design that did not
- have the benefit of a thorough dynamic analysis. In general, the dynamic
- type of an object tends to degrade over time or function call depth. By
- degrade, I mean that it tends to get upcast. A good example is a
- container (barn) that holds animals ({chickens,pigs,horses}). We discard
- some type information as soon as we put the animals in the barn. Chickens
- are still chickens, but we can no longer differentiate between them and
- cows.
-
- Often, we put the animals in the barn a little sooner than is absolutely
- necessary. Often we can avoid downcasting and bloating the interface of
- individual objects by employing one of several techiques. The first is to
- maintain multiple references to each object or subdividing the barn. To
- borrow from the barn analogy further, barns often have pens in them to
- keep kinds of animals together.
-
- The second is to delay upcasting. This is not always possible, but it's
- always worth investigating.
-
- The third is to use a general interface to specific operations. If all
- the animals are in the barn together, there is probably some
- semantic reason why. We may have put them in the barn for the night
- intending to let them sleep. Pigs sleep laying down, horses sleep
- standing up and chickens roost. I've seen a lot of code out there that
- essentially downcasts to achieve calls like pig->lay() and
- chicken->roost() before calling animal->sleep() for the stock. Obviously,
- roost and lay are operations chickens and pigs can decide to do for
- themselves when it's time to sleep. In fact, they actually decide when
- it's time to sleep on their own.
-
- It's rare that I've seen a downcast that couldn't be -reasonably- avoided
- with one of these techniques. I tend to work at avoiding type entropy
- early, during my first pass at the dynamic model when 2nd-order operations
- are emerging. Taking the time to model event classes seems to help here,
- sometimes.
-